package com.gh.service.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gh.dto.ExcelDictDTO;
import com.gh.entity.Dict;
import com.gh.listener.ExcelDtoListener;
import com.gh.mapper.DictMapper;
import com.gh.service.DictService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 数据字典 服务实现类
 * </p>
 *
 * @author Eric
 * @since 2021-09-06
 */
@Slf4j
@Service
public class DictServiceImpl extends ServiceImpl<DictMapper, Dict> implements DictService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void importData(InputStream inputStream) {
        EasyExcel.read(inputStream, ExcelDictDTO.class, new ExcelDtoListener(baseMapper)).sheet().doRead();
    }

    @Override
    public void exportDictToExcel(HttpServletResponse response) {
        //设置下载信息
        response.setContentType("application/vnd.ms-excel");//application/vnd.ms-excel
        response.setCharacterEncoding("utf-8");
        String filename = "dict";
        response.setHeader("Content-disposition", "attachment;filename=" + filename + ".xlsx");
        List<Dict> list = baseMapper.selectList(null);
        List<ExcelDictDTO> dtoList = new ArrayList<>();
        for (Dict dict : list) {
            ExcelDictDTO dictDTO = new ExcelDictDTO();
            BeanUtils.copyProperties(dict, dictDTO);
            dtoList.add(dictDTO);
        }
        try {
            EasyExcel.write(response.getOutputStream()).sheet().doWrite(dtoList);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public List<Dict> listByParentId(Long parentId) {
        //首先查询redis中是否存在缓存列表
        try {
            List<Dict> list = (List<Dict>) redisTemplate.opsForValue().get("dictList:" + parentId);
            //如果存在，直接从redis返回数据列表
            if (list != null && list.size() != 0) {
                log.info("从redis获取数据列表");
                return list;
            }
        } catch (Exception e) {
            log.error("redis服务器异常" + ExceptionUtils.getStackTrace(e));
            e.printStackTrace();
        }
        //如果不存在，查询数据库，然后存入redis
        QueryWrapper<Dict> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("parent_id", parentId);
        List<Dict> dictList = baseMapper.selectList(queryWrapper);
        dictList.forEach(dict -> {
            dict.setHasChildren(findChild(dict.getId()));
        });
        try {
            redisTemplate.opsForValue().set("dictList:" + parentId, dictList, 5, TimeUnit.MINUTES);
            log.info("从redis存数据成功");
        }catch (Exception e){
            log.error("redis服务器异常" + ExceptionUtils.getStackTrace(e));
            e.printStackTrace();
        }

        return dictList;
    }

    @Override
    public List<Dict> getByDictCode(String dictCode) {
        LambdaQueryWrapper<Dict> lambdaQueryWrapper=new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Dict::getDictCode,dictCode);
        Dict dict = baseMapper.selectOne(lambdaQueryWrapper);
        List<Dict> dictList = this.listByParentId(dict.getId());
        return dictList;
    }

    private Boolean findChild(Long id) {
        LambdaQueryWrapper<Dict> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Dict::getParentId, id);
        Integer count = baseMapper.selectCount(lambdaQueryWrapper);
        if (count.intValue() > 0) {
            return true;
        }
        return false;
    }
}
